package com.xbongbong.paas.service.impl;

import com.xbongbong.paas.service.NoticeService;
import com.xbongbong.paas.service.PackageService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.esign.pojo.NoticePojo;
import com.xbongbong.pro.esign.pojo.dto.NoticeDTO;
import com.xbongbong.pro.esign.pojo.vo.NoticeVO;
import com.xbongbong.pro.packageInfo.pojo.vo.BasePackageInfoVO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.domain.dao.NoticeLogDao;
import com.xbongbong.saas.domain.entity.NoticeEntity;
import com.xbongbong.saas.domain.entity.NoticeLogEntity;
import com.xbongbong.saas.model.NoticeModel;
import com.xbongbong.saas.service.OpportunityService;
import com.xbongbong.sys.model.FeeCompanyModel;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author long
 * @version v1.0
 * @date 2020/10/13 10:23
 * @since v1.0
 */
@Service("noticeService")
public class NoticeServiceImpl implements NoticeService {
    private static final Logger LOG = LoggerFactory.getLogger(NoticeServiceImpl.class);

    public static final String NOTICE_COOKIE_KEY = "closedNoticeIds";

    @Resource
    private FeeCompanyModel feeCompanyModel;
    @Resource
    private NoticeModel noticeModel;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private OpportunityService opportunityService;
    @Resource
    private PackageService packageService;
    @Resource
    private NoticeLogDao noticeLogDao;

    @Override
    public NoticeVO get(BaseDTO baseDTO, HttpServletRequest request) throws XbbException {
        NoticeVO noticeVO = new NoticeVO();
        NoticePojo noticePojo = new NoticePojo();
        Map<String, Object> param = new HashMap();
        List<String> noticeIdList = null;
        String corpid = baseDTO.getCorpid();
        param.put("userId", baseDTO.getUserId());
        param.put("corpid", corpid);
        param.put("del", 0);
        List<NoticeLogEntity> entitys = noticeLogDao.findEntitys(param);
        //获取用户关闭的通知
        if(CollectionUtils.isNotEmpty(entitys)){
            noticeIdList = entitys.stream().map(NoticeLogEntity::getNoticeId).map(noticeId->String.valueOf(noticeId)).collect(Collectors.toList());
        }
        param.clear();
        NoticeEntity noticeEntity = null;
        //查询套餐类型是否符合
        if(!haveFeeTypePermission(corpid)){
            return noticeVO;
        }

        //查询时间没有过期的通知
        param.put("nowTime", DateUtil.getInt());
        param.put("del", 0);
        List<NoticeEntity> noticeList = noticeModel.findEntitys(param);
        if(CollectionUtils.isNotEmpty(noticeList)){
            //获取到该用户可以查看的通知
            noticeEntity = filterNoticeList(noticeList, baseDTO.getLoginUser(), noticeIdList);
            if (Objects.isNull(noticeEntity)) {
                return noticeVO;
            }
            noticePojo.setId(noticeEntity.getId());
            noticePojo.setButtonContent(noticeEntity.getButtonContent());
            noticePojo.setNoticeContent(noticeEntity.getNoticeContent());
            noticePojo.setPopupContent(noticeEntity.getPopupContent());
            noticePojo.setTitle(noticeEntity.getTitle());
            noticeVO.setNoticePojo(noticePojo);
        }
        return noticeVO;
    }

    @Override
    public BaseVO closeNotice(NoticeDTO noticeDTO, HttpServletRequest request, HttpServletResponse response) throws XbbException {
        //是否创建机会flag (1代表创建)
        Integer isCreateOpportunity = noticeDTO.getIsCreateOpportunity();
        String title = noticeDTO.getTitle();
        NoticeLogEntity noticeLogEntity = new NoticeLogEntity();
        noticeLogEntity.setCorpid(noticeDTO.getCorpid());
        noticeLogEntity.setNoticeId(noticeDTO.getNoticeId().longValue());
        noticeLogEntity.setUserId(noticeDTO.getUserId());
        int now = DateUtil.getTodayInt();
        noticeLogEntity.setAddTime(now);
        noticeLogEntity.setUpdateTime(now);
        noticeLogDao.insert(noticeLogEntity);
        autoAddOpp(isCreateOpportunity, noticeDTO.getCorpid(), noticeDTO.getLoginUserName(), title);
        return new BaseVO();
    }

    private void autoAddOpp(Integer isCreateOpportunity, final String corpid , final String userName , final String  noticeName) throws XbbException{
        if (!Objects.equals(isCreateOpportunity, 1)) {
            return;
        }
        Runnable runnable = () -> {
            try {
                opportunityService.autoAdd(corpid, userName, noticeName);
            } catch (XbbException e) {
                LOG.error("listBatchService.handoverInsertUser error", e);
            }
        };
        threadPoolBeanConfig.listBatchThreadPool().execute(runnable);
    }

    private Boolean haveFeeTypePermission(String corpid) throws XbbException{
        BasePackageInfoVO basePackageInfoFromRedis = packageService.getBasePackageInfoFromRedis(corpid);
        Integer feeType = basePackageInfoFromRedis.getFeeType();
        if(!Objects.equals(feeType, PackageTypeEnum.ADVANCED.getType()) && !Objects.equals(feeType, PackageTypeEnum.ULTIMATE.getType())){
            // 不是高级版或旗舰版无法获取通知
            return false;
        }
        return true;
    }

    private NoticeEntity filterNoticeList(List<NoticeEntity> noticeList, UserVO loginUser, List<String> userClosedNoticeList){
        Boolean isBoss = loginUser.isBoss();
        Boolean isAdmin = loginUser.isAdmin();
        //倒序删除
        for(int i = noticeList.size() -1 ; i >= 0 ;i--){
            NoticeEntity noticeEntity = noticeList.get(i);
            //如果设置了限制公司，查看用户所在公司是否需要推送
            if(noticeEntity.getCorpLimit() == 1){
                List<String> enabledCorpidList = analysisCorpids(noticeEntity.getPartnerCorpids());
                if(CollectionUtils.isEmpty(enabledCorpidList) || (!enabledCorpidList.contains(loginUser.getCorpid()))){
                    noticeList.remove(i);
                    continue;
                }
            }
            //身份权限判定
            if(!havePermission(noticeEntity,isBoss,isAdmin)){
                noticeList.remove(i);
            }
        }
        //筛选掉用户已经点击过叉掉的通知
        filterClosedNoticeList(noticeList,userClosedNoticeList);
        //存在多个可以查看的通知时，返回最新的一个
        NoticeEntity lastNotice = getLastNotice(noticeList);
        return  lastNotice;
    }

    /**
     * 因为partnerCorpids的值是“123\n456\n678”，使用\n分割的，所以需要解析一下
     * @param partnerCorpids
     * @return
     */
    private List<String>  analysisCorpids(String partnerCorpids){
        List<String> corpidList = null;
        if(StringUtil.isNotEmpty(partnerCorpids)){
            try {
                corpidList =  Arrays.asList(partnerCorpids.split("\n"));
            }catch (Exception e){
                LOG.error("解析partnerCorpids出错,partnerCorpids-{}-",partnerCorpids);
            }
        }
        return corpidList;
    }

    /**
     *
     * @param noticeEntity
     * @param isBoss
     * @param isAdmin
     * @return 返回true,表示这个人拥有查看通知的权限
     */
    private Boolean havePermission(NoticeEntity noticeEntity , Boolean isBoss, Boolean isAdmin){
        Boolean  partnerIsBoss = noticeEntity.getPartnerIsBoss() == 1;
        Boolean  partnerIsAdmin = noticeEntity.getPartnerIsAdmin() == 1;
        //两个都开启了
        if(partnerIsBoss && partnerIsAdmin){
            if((!isBoss) && (!isAdmin)){
                //这个人既不是老板也不是管理员
                return false;
            }
        }
        //只开启了老板的限制
        if(partnerIsBoss){
            if(!isBoss){
                return false;
            }
        }
        //只开启了管理员的限制
        if(partnerIsAdmin){
            if(!isAdmin){
                return false;
            }
        }

        return true;
    }

    private void filterClosedNoticeList(List<NoticeEntity> noticeList , List<String> userClosedNoticeList){
        NoticeEntity notice = null;
        if(CollectionUtils.isNotEmpty(userClosedNoticeList)){
            for(int i = noticeList.size() -1 ; i >= 0 ;i--){
                notice =  noticeList.get(i);
                //用户已经查看过的通知，移除
                if(userClosedNoticeList.contains(notice.getId().toString())){
                    noticeList.remove(i);
                }
            }
        }
    }

    private NoticeEntity getLastNotice(List<NoticeEntity> noticeList){
        NoticeEntity result  = null;
        if(CollectionUtils.isNotEmpty(noticeList)){
            if(noticeList.size() == 1){
                result =  noticeList.get(0);
            }else{
                //按照创建时间倒序
                Collections.sort(noticeList, new Comparator<NoticeEntity>() {
                    @Override
                    public int compare(NoticeEntity o1, NoticeEntity o2) {
                        return o2.getAddTime() - o1.getAddTime();
                    }
                });
                result = noticeList.get(0);
            }

        }
        return result;
    }
}
